/**
 * @file    param_mng.c
 * @brief   参数管理
 * @author  Liuwei 
 * @version 1.0.3
 * @date    2024-06-17
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-19 <td>1.0.1     <td>Liuwei   <td>首次创建
 * <tr><td>2024-01-03 <td>1.0.2     <td>Liuwei   <td>修改生产厂家为Bar Code码
 * <tr><td>2024-06-17 <td>1.0.3     <td>Liuwei   <td>添加EEPROM故障检测
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "param_mng.h"
//#include "ser_nvm.h"
#include "If_nvm.h"
#include "param_default.h"
#include <string.h>
#include "cfg_prj.h"
#include "soc_calc.h"
#include "mcu_type.h"
#include "var_mng.h"
#include "drv_mcu.h"
#include "diagnosis.h"
/* macro/define --------------------------------------------------------------*/
#define PARAM_FLAG        (0x5AA5)
#define PARAM_TRY_TIMES   (5)
/* typedef -------------------------------------------------------------------*/

/* local functions -----------------------------------------------------------*/
static void param_check_u16_vrc(uint8_t cmd ,uint16_t *par , uint16_t dft , uint16_t min , uint16_t max);
/* static variables ----------------------------------------------------------*/
static uint16_t param_buf[PAR_ID_BUF_SIZE] = {0};
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief 系统参数管理初始化，读取NVM内部参数
 */
void param_init(void)
{
    uint16_t read_flag = 0;
	uint8_t i = 0;
    /* 检测基本参数 */
	for(i = 0 ;i < PARAM_TRY_TIMES ; ++ i)
	{
		If_nvm_read_data(NVM_PARAM_CHK_ADDR , (uint8_t *)&read_flag , 2);

		if(PARAM_FLAG == read_flag)
			break;
		
		mcu_delay_ms(10);
	}
	
    if(PARAM_FLAG == read_flag)
    {
        If_nvm_read_data(NVM_PARAM_ST_ADDR , (uint8_t *)&param_buf , PAR_ID_BUF_SIZE * 2);
		
		param_valid_check(PARAM_CHECK);
    }
    else
    {
	    param_buf[PAR_ID_CB_CC_K] = PAR_K_DFT;     
		param_buf[PAR_ID_CB_CC_B] = PAR_B_DFT;
		param_buf[PAR_ID_CB_DC_K] = PAR_K_DFT;
		param_buf[PAR_ID_CB_DC_B] = PAR_B_DFT;
		for( i = 0;i < 16; ++ i)
		{
			param_buf[PAR_ID_CB_CV01_K + i * 2] = PAR_K_DFT;
			param_buf[PAR_ID_CB_CV01_B + i * 2] = PAR_B_DFT;
		}
		param_buf[PAR_ID_CB_BV_K] = PAR_K_DFT;
		param_buf[PAR_ID_CB_BV_B] = PAR_B_DFT;     
		for( i = 0;i < 8; ++ i)
		{
			param_buf[PAR_ID_CB_CT_K + i * 2] = PAR_K_DFT;
			param_buf[PAR_ID_CB_CT_B + i * 2] = PAR_B_DFT;
		}
		
    	for( i = 0;i < 15; ++ i)
		{
			param_buf[PAR_ID_BMS_CODE + i] = 0;
		}
		strcpy((char *)&param_buf[PAR_ID_BMS_CODE] ,PAR_DFT_BMS_SN);
		param_buf[PAR_ID_BMS_YEAR] = PAR_DFT_BMS_YEAR;  
		param_buf[PAR_ID_BMS_MONTH] = PAR_DFT_BMS_MONTH;
		param_buf[PAR_ID_BMS_DAY] = PAR_DFT_BMS_DATE;
		for( i = 0;i < 15; ++ i)
		{
			param_buf[PAR_ID_SN_CODE + i] = 0;
		}
		strcpy((char *)&param_buf[PAR_ID_SN_CODE] ,PAR_DFT_PACK_SN);
		param_buf[PAR_ID_PACK_YEAR] = PAR_DFT_PACK_YEAR;
		param_buf[PAR_ID_PACK_MONTH] = PAR_DFT_PACK_MONTH;
		param_buf[PAR_ID_PACK_DAY] = PAR_DFT_PACK_DATE;
		// bar Code 码 蓝牙名称
		for( i = 0;i < 15; ++ i)
		{
			param_buf[PAR_ID_MFT_CODE + i] = 0x2020;
		}
		strcpy((char *)&param_buf[PAR_ID_MFT_CODE] ,PAR_DFT_PACK_MFT);
		
		param_buf[PAR_ID_CB_CELL_NUM] = PAR_DFT_CELL_NUM;
		
		param_buf[PAR_ID_CB_ZERO_SET]= 0;  //需要加上，避免烧录零点丢失
		
		param_factory_setting();
		If_nvm_save_data(NVM_PARAM_ST_ADDR ,  (uint8_t *)&param_buf , PAR_ID_BUF_SIZE * 2);
		read_flag = PARAM_FLAG;
		If_nvm_save_data(NVM_PARAM_CHK_ADDR ,  (uint8_t *)&read_flag , 2);
		
		// ## LW++ 添加EEP异常告警检测
		for(i = 0 ;i < PARAM_TRY_TIMES ; ++ i)
		{
			If_nvm_read_data(NVM_PARAM_CHK_ADDR , (uint8_t *)&read_flag , 2);

			if(PARAM_FLAG == read_flag)
				break;
		
			mcu_delay_ms(10);
		}
		
		if(PARAM_FLAG != read_flag)
		{
			diag_set_alarm(ALM_ID_EEP , 1);
		}
		
		// ## LW end
    }
}

/**
 * @brief  参数检测有效性
 * @param  cmd
 */
void param_valid_check(uint8_t cmd)
{
	/* 单体过压 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_COV_ALM_VAL] , PAR_DFT_COV_ALM_VAL , 2500 , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_COV_ALM_DLY] , PAR_DFT_COV_ALM_DLY , 100  , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_COV_ALM_RCV] , PAR_DFT_COV_ALM_RCV , 1400 , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_COV_PRP_VAL] , PAR_DFT_COV_PRP_VAL , 1400 , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_COV_PRP_DLY] , PAR_DFT_COV_PRP_DLY , 100  , 4000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_COV_PRP_RCV] , PAR_DFT_COV_PRP_RCV , 1400 , 4500);
	/* 单体欠压 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CUV_ALM_VAL] , PAR_DFT_CUV_ALM_VAL , 1400 , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CUV_ALM_DLY] , PAR_DFT_CUV_ALM_DLY , 100  , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CUV_ALM_RCV] , PAR_DFT_CUV_ALM_RCV , 1400 , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CUV_PRP_VAL] , PAR_DFT_CUV_PRP_VAL , 1400 , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CUV_PRP_DLY] , PAR_DFT_CUV_PRP_DLY , 100  , 4000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CUV_PRP_RCV] , PAR_DFT_CUV_PRP_RCV , 1400 , 4500);
	/* 总压过压 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_VAL] , PAR_DFT_BOV_ALM_VAL , 1500 , 7000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_DLY] , PAR_DFT_BOV_ALM_DLY , 100  , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_RCV] , PAR_DFT_BOV_ALM_RCV , 1500 , 7000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_VAL] , PAR_DFT_BOV_PRP_VAL , 1500 , 7000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_DLY] , PAR_DFT_BOV_PRP_DLY , 100  , 4000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_RCV] , PAR_DFT_BOV_PRP_RCV , 2500 , 7000);
	/* 总压欠压 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_VAL] , PAR_DFT_BUV_ALM_VAL , 1500 , 7000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_DLY] , PAR_DFT_BUV_ALM_DLY , 100  , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_RCV] , PAR_DFT_BUV_ALM_RCV , 1500 , 7000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_VAL] , PAR_DFT_BUV_PRP_VAL , 1500 , 7000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_DLY] , PAR_DFT_BUV_PRP_DLY , 100  , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_RCV] , PAR_DFT_BUV_PRP_RCV , 1500 , 7000);
	/* 充电过流 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_ALM_VAL] , PAR_DFT_OCC_ALM_VAL , 50  , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_ALM_DLY] , PAR_DFT_OCC_ALM_DLY , 50  , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_ALM_RCV] , PAR_DFT_OCC_ALM_RCV , 100  , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_PRP_VAL] , PAR_DFT_OCC_PRP_VAL , 50  , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_PRP_DLY] , PAR_DFT_OCC_PRP_DLY , 50  , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_RCV_DLY] , PAR_DFT_OCC_RCV_DLY , 5    , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC_LOCK_TIMES] , PAR_DFT_OCC_LOCK_TIMES , 3    , 0xffff);
	/* 充电过流2 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC2_PRP_VAL] , PAR_DFT_OCC2_PRP_VAL , 50  , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC2_PRP_DLY] , PAR_DFT_OCC2_PRP_DLY , 50  , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC2_RCV_DLY] , PAR_DFT_OCC2_RCV_DLY , 5    , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCC2_LOCK_TIMES] , PAR_DFT_OCC2_LOCK_TIMES , 3    , 0xffff);
	/* 放电过流1 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_ALM_VAL] , PAR_DFT_OCD_ALM_VAL , 50 , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_ALM_DLY] , PAR_DFT_OCD_ALM_DLY , 100  , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_ALM_RCV] , PAR_DFT_OCD_ALM_RCV , 50 , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_PRP_VAL] , PAR_DFT_OCD_PRP_VAL , 50 , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_PRP_DLY] , PAR_DFT_OCD_PRP_DLY , 100  , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_RCV_DLY] , PAR_DFT_OCD_RCV_DLY , 5    , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD1_LOCK_TIMES] , PAR_DFT_OCD_LOCK_TIMES , 3    , 0xffff);
	/* 放电过流2 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD2_PRP_VAL] , PAR_DFT_OCD2_PRP_VAL , 50  , 6000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD2_PRP_DLY] , PAR_DFT_OCD2_PRP_DLY , 100  , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD2_RCV_DLY] , PAR_DFT_OCD2_RCV_DLY , 5    , 10000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OCD2_LOCK_TIMES] , PAR_DFT_OCD2_LOCK_TIMES , 0    , 0xffff);
	/* 充电过温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTC_ALM_VAL] , PAR_DFT_OTC_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTC_ALM_DLY] , PAR_DFT_OTC_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTC_ALM_RCV] , PAR_DFT_OTC_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTC_PRP_VAL] , PAR_DFT_OTC_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTC_PRP_DLY] , PAR_DFT_OTC_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTC_PRP_RCV] , PAR_DFT_OTC_PRP_RCV , 100   , 1700);
	/* 充电欠温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTC_ALM_VAL] , PAR_DFT_UTC_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTC_ALM_DLY] , PAR_DFT_UTC_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTC_ALM_RCV] , PAR_DFT_UTC_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTC_PRP_VAL] , PAR_DFT_UTC_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTC_PRP_DLY] , PAR_DFT_UTC_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTC_PRP_RCV] , PAR_DFT_UTC_PRP_RCV , 100   , 1700);
	/* 放电过温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTD_ALM_VAL] , PAR_DFT_OTD_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTD_ALM_DLY] , PAR_DFT_OTD_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTD_ALM_RCV] , PAR_DFT_OTD_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTD_PRP_VAL] , PAR_DFT_OTD_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTD_PRP_DLY] , PAR_DFT_OTD_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTD_PRP_RCV] , PAR_DFT_OTD_PRP_RCV , 100   , 1700);
	/* 放电欠温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTD_ALM_VAL] , PAR_DFT_UTD_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTD_ALM_DLY] , PAR_DFT_UTD_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTD_ALM_RCV] , PAR_DFT_UTD_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTD_PRP_VAL] , PAR_DFT_UTD_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTD_PRP_DLY] , PAR_DFT_UTD_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTD_PRP_RCV] , PAR_DFT_UTD_PRP_RCV , 100   , 1700);
	/* 环境过温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTE_ALM_VAL] , PAR_DFT_OTE_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTE_ALM_DLY] , PAR_DFT_OTE_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTE_ALM_RCV] , PAR_DFT_OTE_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTE_PRP_VAL] , PAR_DFT_OTE_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTE_PRP_DLY] , PAR_DFT_OTE_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTE_PRP_RCV] , PAR_DFT_OTE_PRP_RCV , 100   , 1700);
	/* 环境欠温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTE_ALM_VAL] , PAR_DFT_UTE_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTE_ALM_DLY] , PAR_DFT_UTE_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTE_ALM_RCV] , PAR_DFT_UTE_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTE_PRP_VAL] , PAR_DFT_UTE_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTE_PRP_DLY] , PAR_DFT_UTE_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_UTE_PRP_RCV] , PAR_DFT_UTE_PRP_RCV , 100   , 1700);
	/* MOS高温 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTM_ALM_VAL] , PAR_DFT_OTM_ALM_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTM_ALM_DLY] , PAR_DFT_OTM_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTM_ALM_RCV] , PAR_DFT_OTM_ALM_RCV , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTM_PRP_VAL] , PAR_DFT_OTM_PRP_VAL , 100   , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTM_PRP_DLY] , PAR_DFT_OTM_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_OTM_PRP_RCV] , PAR_DFT_OTM_PRP_RCV , 100   , 1700);
	/* 温差过大 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_TDIFF_ALM_VAL] , PAR_DFT_TDIFF_ALM_VAL , 2   , 250);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_TDIFF_ALM_DLY] , PAR_DFT_TDIFF_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_TDIFF_ALM_RCV] , PAR_DFT_TDIFF_ALM_RCV , 2   , 250);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_TDIFF_PRP_VAL] , PAR_DFT_TDIFF_PRP_VAL , 2   , 250);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_TDIFF_PRP_DLY] , PAR_DFT_TDIFF_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_TDIFF_PRP_RCV] , PAR_DFT_TDIFF_PRP_RCV , 2   , 250);
	/* 压差过大 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_VDIFF_ALM_VAL] , PAR_DFT_VDIFF_ALM_VAL , 50   , 2000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_VDIFF_ALM_DLY] , PAR_DFT_VDIFF_ALM_DLY , 100 , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_VDIFF_ALM_RCV] , PAR_DFT_VDIFF_ALM_RCV , 50  , 2000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_VDIFF_PRP_VAL] , PAR_DFT_VDIFF_PRP_VAL , 50   , 2000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_VDIFF_PRP_DLY] , PAR_DFT_VDIFF_PRP_DLY , 100 , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_VDIFF_PRP_RCV] , PAR_DFT_VDIFF_PRP_RCV , 50   , 2000);
	/* SOC过低 */
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOCL_ALM_VAL] , PAR_DFT_SOCL_ALM_VAL , 0   , 100);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOCL_ALM_DLY] , PAR_DFT_SOCL_ALM_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOCL_ALM_RCV] , PAR_DFT_SOCL_ALM_RCV , 0   , 100);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOCL_PRP_VAL] , PAR_DFT_SOCL_PRP_VAL , 0   , 100);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOCL_PRP_DLY] , PAR_DFT_SOCL_PRP_DLY , 100   , 60000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOCL_PRP_RCV] , PAR_DFT_SOCL_PRP_RCV , 0   , 100);
	
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BLC_VOLT]       , PAR_DFT_BLC_OP_VOLT , 1500, 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BLC_VDIFF]      , PAR_DFT_BLC_OP_VDIFF, 5   , 1000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_HOT_START_TEMP] , PAR_DFT_HOT_START_T , 100  , 900);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_HOT_STOP_TEMP]  , PAR_DFT_HOT_STOP_T  , 100  , 1000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_FAN_START_TEMP] , PAR_DFT_FAN_START_T , 100  , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_FAN_STOP_TEMP]  , PAR_DFT_FAN_STOP_T  , 100  , 1700);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_FULL_CHG_CURR]  , PAR_DFT_FULL_CHG_CURR  , 100   , 5000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_IDE_SLP_VOLT]   , PAR_DFT_SLEEP_VOLT  , 2000   , 4500);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_IDE_SLP_DLY]    , PAR_DFT_SLEEP_DLY  , 5   , 22000);//15天
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_IDE_SLP_CURR]   , PAR_DFT_SLEEP_CURR  , 5   , 100);  // 最大10A	
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_DAMP_FACTOR]    , PAR_DFT_DAMP_FECTOR  , 50   , 2000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BATT_TYPE]      , PAR_DFT_BATT_TYPE  , 0      , 3   );
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOP_CC]         , PAR_DFT_SOP_CC  , 100   , 3000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOP_DC]         , PAR_DFT_SOP_DC  , 100   , 3000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_FCHG_RECV_SOC]  , FCHG_RECV_SOC  , 90   , 100);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CHG_VOLT]       , PAR_DFT_CHG_VOLT  , 2000   , 7000);

	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_IDE_SLEEP_DLY]    , PAR_DFT_IDE_SLP_DLY  , 120   , 22000);//15天	
    
    param_check_u16_vrc(cmd ,&param_buf[PAR_ID_CYCLE_COEFF]       , PAR_DFT_CYCLE_COEFF  , 70   , 110);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BLC_MODE]       , PAR_DFT_BLC_OPEN_MODE , PARAM_BLC_MODE_CHG   , PARAM_BLC_MODE_STATIC);
	
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_WIFI_CYCLE]     , PAR_DFT_WIFI_CYCLE  , 30   , 18000);
	param_check_u16_vrc(cmd ,&param_buf[PAR_ID_WIFI_REP_EN]    , 0x5AA5  , 0   , 0xFFFF);

	// 只检测不还原
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_CB_CELL_NUM]    , PAR_DFT_CELL_NUM  , PAR_CELL_NUM_MIN   , PAR_CELL_NUM_MAX);
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_CB_TEMP_NUM]    , PAR_DFT_TEMP_NUM  , PAR_TEMP_NUM_MIN   , PAR_TEMP_NUM_MAX);
		
	if(PAR_DFT_CELL_NUM != param_buf[PAR_ID_CB_CELL_NUM])
	{
		/* 总压过压 */
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_VAL] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_COV_ALM_VAL * 0.1, 2500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_RCV] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_COV_ALM_RCV * 0.1, 2500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_VAL] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_COV_PRP_VAL * 0.1, 2500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_RCV] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_COV_PRP_RCV * 0.1, 2500 , 7000);
		/* 总压欠压 */
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_VAL] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_CUV_ALM_VAL * 0.1, 1500 , 6000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_RCV] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_CUV_ALM_RCV * 0.1, 1500 , 6000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_VAL] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_CUV_PRP_VAL * 0.1, 1500 , 6000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_RCV] , param_buf[PAR_ID_CB_CELL_NUM] * PAR_DFT_CUV_PRP_RCV * 0.1, 1500 , 6000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_FULL_CHG_VOLT] , PAR_DFT_FULL_CHG_VOLT * param_buf[PAR_ID_CB_CELL_NUM] / PAR_DFT_CELL_NUM, 1500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOP_DV]      , PAR_DFT_SOP_DV * param_buf[PAR_ID_CB_CELL_NUM] / PAR_DFT_CELL_NUM , 100   , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOP_CV]   	, PAR_DFT_SOP_CV * param_buf[PAR_ID_CB_CELL_NUM] / PAR_DFT_CELL_NUM , 100   , 7000);

	}
	else
	{
		/* 总压过压 */
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_VAL] , PAR_DFT_BOV_ALM_VAL , 2500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_ALM_RCV] , PAR_DFT_BOV_ALM_RCV , 2500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_VAL] , PAR_DFT_BOV_PRP_VAL , 2500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BOV_PRP_RCV] , PAR_DFT_BOV_PRP_RCV , 2500 , 7000);
		/* 总压欠压 */
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_VAL] , PAR_DFT_BUV_ALM_VAL, 1500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_ALM_RCV] , PAR_DFT_BUV_ALM_RCV, 1500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_VAL] , PAR_DFT_BUV_PRP_VAL, 1500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BUV_PRP_RCV] , PAR_DFT_BUV_PRP_RCV, 1500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_FULL_CHG_VOLT] , PAR_DFT_FULL_CHG_VOLT, 1500 , 7000);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOP_DV]      , PAR_DFT_SOP_DV  , 100   , 700);
		param_check_u16_vrc(cmd ,&param_buf[PAR_ID_SOP_CV]      , PAR_DFT_SOP_CV  , 100   , 700);
	  
	}
	// ## LW++ 添加满充容量、标称容量、SOH异常检测 -只检测不恢复默认
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_STD_CAP]          , PAR_DFT_STD_CAP   , 1000   , 65500);
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_FULL_CAP]         , PAR_DFT_FULL_CAP  , 1000   , 65500);
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_SOH]              , 100               , 50     , 120);
	
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_IDE_SC_CURR]      , PAR_DFT_SC_CURR  , 500   , 4000);
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_IDE_SC_DLY]       , PAR_DFT_SC_DLY   , 10   , 600);
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_FULL_CAP]         , PAR_DFT_FULL_CAP  , 1000   , 65500);
	
	param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_IDE_SLEEP_DELAY]  , PAR_DFT_IDE_SLEEP_DLY , 360 , 54000);
	
    param_check_u16_vrc(cmd ,&param_buf[PAR_ID_BATT_SELF_POW]    , CFG_SYS_IDDQ      , 20     , 150);
	// ## LW end
}

/**
 * @brief  设置缓冲区参数
 * @param  par_id ：参数ID
 * @param  set_val :参数值
 * @return uint8_t 
 */
uint8_t param_set_data(uint16_t par_id , uint16_t set_val)
{
	uint8_t ret = FALSE;
    if(par_id >= PAR_ID_BUF_SIZE)
        return FALSE;
    
    if(param_buf[par_id] != set_val)
    {
        param_buf[par_id] = set_val;

        ret = If_nvm_save_data(par_id * 2 + NVM_PARAM_ST_ADDR , (uint8_t *)&param_buf[par_id] , 2);
    }

    return ret;
}

/**
 * @brief  获取参数缓冲区域参数
 * @param  par_id : 参数 ID
 * @param  pval : 参数值
 * @return uint8_t 
 */
uint16_t param_get_data(uint16_t par_id)
{
    if(par_id >= PAR_ID_BUF_SIZE)
        return FALSE;
    
    return param_buf[par_id];
}

/**
 * @brief  连续读取多个参数
 * @param  start_addr : 开始地址
 * @param  num : 读取数量
 * @param  rd_buf :读取缓冲区 
 * @return uint8_t :读取结果
 */
uint8_t param_get_multi_data(uint16_t start_addr , uint16_t num ,uint16_t *rd_buf)
{
    uint8_t i = 0;
    if(start_addr + num >= PAR_ID_BUF_SIZE)
        return FALSE;
    
    for(i = 0;i < num; ++ i)
    {
        rd_buf[i] = param_buf[start_addr + i];
    }

    return TRUE;
}

/**
 * @brief  连续设置多个参数
 * @param  start_addr : 开始地址
 * @param  num : 读取数量
 * @param  rd_buf :读取缓冲区 
 * @return uint8_t :读取结果
 */
uint8_t param_set_multi_data(uint16_t start_addr , uint16_t num ,uint16_t *wr_buf)
{
    uint8_t i = 0;
    if(start_addr + num >= PAR_ID_BUF_SIZE)
        return FALSE;
    
    for(i = 0;i < num; ++ i)
    {
        param_buf[start_addr + i] = wr_buf[i];
    }
    
    return TRUE;
}

float param_convert_float(uint8_t type ,uint16_t data_val)
{
	float fdata = 0;
	switch(type)
	{
		case PARAM_TEMP :
			fdata = data_val * PARAM_TEMP_FACTOR + PARAM_TEMP_OFFSET;
			break;
		case PARAM_CAP  :
			fdata = data_val * PARAM_CAP_FACTOR + PARAM_CAP_OFFSET;
			break;
		case PARAM_CURR :
			fdata = data_val * PARAM_CURR_FACTOR + PARAM_CURR_OFFSET;
			break;
		case PARAM_BVOLT:
			fdata = data_val * PARAM_BV_FACTOR + PARAM_BV_OFFSET;
			break;
	}
	return fdata;
}

uint16_t param_convert_u16(uint8_t type ,float data_val)
{
	float fdata = 0;
	switch(type)
	{
		case PARAM_TEMP :
			fdata = (double)(data_val - PARAM_TEMP_OFFSET) / PARAM_TEMP_FACTOR;
			break;
		case PARAM_CAP  :
			fdata = (float)(data_val - PARAM_CAP_OFFSET) / PARAM_CAP_FACTOR;
			break;
		case PARAM_CURR :
			fdata = (float)(data_val - PARAM_CURR_OFFSET) / PARAM_CURR_FACTOR;
			break;
		case PARAM_BVOLT:
			fdata = (float)(data_val - PARAM_BV_OFFSET) / PARAM_BV_FACTOR;
			break;
	}
	return fdata;
}

/**
 * @brief 系统参数恢复出厂设置
 */
void param_factory_setting(void)
{
	param_buf[PAR_ID_CB_L1_SOC] = PAR_CB_L1_SOC;   
	param_buf[PAR_ID_CB_L1_VOLT] = PAR_CB_L1_VOLT; 
	param_buf[PAR_ID_CB_L2_SOC] = PAR_CB_L2_SOC;
	param_buf[PAR_ID_CB_L2_VOLT] = PAR_CB_L2_VOLT;
	param_buf[PAR_ID_CB_H1_SOC] = PAR_CB_H1_SOC;
	param_buf[PAR_ID_CB_H1_VOLT] = PAR_CB_H1_VOLT;
	param_buf[PAR_ID_CB_H2_SOC] = PAR_CB_H2_SOC;
	param_buf[PAR_ID_CB_H2_VOLT] = PAR_CB_H2_VOLT;

    param_buf[PAR_ID_PCS_CAN_TYPE] = PAR_DFT_PCS_CAN_TYPE;
    param_buf[PAR_ID_PCS_RS485_TYPE] = PAR_DFT_PCS_RS485_TYPE;
	  
	param_buf[PAR_ID_STD_CAP] = PAR_DFT_STD_CAP;
	param_buf[PAR_ID_FULL_CAP] = PAR_DFT_FULL_CAP;
	param_buf[PAR_ID_REAL_CAP] = PAR_DFT_REAL_CAP;     
	param_buf[PAR_ID_RSOC] = PAR_DFT_REAL_SOC;
	
	soc_calc_set_soc(PAR_DFT_REAL_SOC);   //解决上电SOC为0
	
	param_buf[PAR_ID_CYCLE] = 0;       
    param_buf[PAR_ID_SOH] = 100;   
	param_buf[PAR_ID_SOH_ST_CYCLE] = 0;
	param_buf[PAR_ID_ACC_CHG_AH_H] = 0;
	param_buf[PAR_ID_ACC_CHG_AH_L] = 0;  
	param_buf[PAR_ID_ACC_DSG_AH_H] = 0;
	param_buf[PAR_ID_ACC_DSG_AH_L] = 0;
	param_buf[PAR_ID_CYCLE_COEFF] = PAR_DFT_CYCLE_COEFF;
	param_buf[PAR_ID_BATT_TYPE] = PAR_DFT_BATT_TYPE;
	param_buf[PAR_ID_BATT_MFT] = 0; 
	param_buf[PAR_ID_BATT_SELF_POW] = 1000 * CFG_SYS_IDDQ;
	param_buf[PAR_ID_DAMP_FACTOR] = PAR_DFT_DAMP_FECTOR;
	param_buf[PAR_ID_BLC_MODE] = PAR_DFT_BLC_OPEN_MODE;
	param_buf[PAR_ID_SC_PRP_TIMES] = 0;
	param_buf[PAR_ID_OCC_PRP_TIMES] = 0;
	param_buf[PAR_ID_OCD_PRP_TIMES] = 0;
	param_buf[PAR_ID_COV_PRP_TIMES] = 0;
	param_buf[PAR_ID_BOV_PRP_TIMES] = 0;
	param_buf[PAR_ID_BUV_PRP_TIMES] = 0;
	param_buf[PAR_ID_OTC_PRP_TIMES] = 0;
	param_buf[PAR_ID_UTC_PRP_TIMES] = 0;
	param_buf[PAR_ID_OTD_PRP_TIMES] = 0;
	param_buf[PAR_ID_UTD_PRP_TIMES] = 0;
	param_buf[PAR_ID_RESTART_TIMES] = 0;
	
	//param_buf[PAR_ID_CB_CELL_NUM] = PAR_DFT_CELL_NUM;
	
	param_buf[PAR_ID_RS485_RATE] = 0;
	param_buf[PAR_ID_CAN_RATE] = PAR_DFT_CAN_RATE;
	param_buf[PAR_ID_SOC_CFG] = (PAR_DFT_SOC_CALIB << 0x04) + PAR_DFT_SOC_STANDY;
	/*修改20241029*/
	param_buf[PAR_ID_FUNC_CFG] = PAR_DFT_FUNC_HOT 
		+ (PAR_DFT_FUNC_BEEP << FUNC_BEEP_POS) 
		+ (PAR_DFT_FUNC_VTD << FUNC_VTD_POS) 
		+ (PAR_DFT_FUNC_GPS << FUNC_GPS_POS) 
		+ (PAR_DFT_FUNC_NLED << FUNC_NSOC_POS)
		+ (PAR_DFT_FUNC_RLED << FUNC_RSOC_POS)
		+ (PAR_DFT_FUNC_MOSLED << FUNC_MOSLED_POS)
		+ (PAR_DFT_FUNC_FENG <<  FUNC_FENG_POS);
	
	param_valid_check(PARAM_RESET);
}

void param_restore_default(void)
{
    param_buf[PAR_ID_BATT_TYPE] = PAR_DFT_BATT_TYPE;
	param_buf[PAR_ID_BATT_MFT] = 0; 
	param_buf[PAR_ID_DAMP_FACTOR] = PAR_DFT_DAMP_FECTOR;
	param_buf[PAR_ID_BATT_SELF_POW] = 1000 * CFG_SYS_IDDQ;  
}

void param_save_all(void)
{
    If_nvm_save_data(NVM_PARAM_ST_ADDR ,  (uint8_t *)&param_buf , PAR_ID_BUF_SIZE * 2);
}

void param_set_cell_num(uint8_t cell_num)
{
	if((cell_num >= 8) && (cell_num <= 16))
	{
		param_set_data(PAR_ID_CB_CELL_NUM , cell_num);
		
		param_check_u16_vrc(PARAM_CHECK ,&param_buf[PAR_ID_CB_CELL_NUM]    , PAR_DFT_CELL_NUM  , PAR_CELL_NUM_MIN   , PAR_CELL_NUM_MAX);
		/* 总压过压 */
		param_set_data(PAR_ID_BOV_ALM_VAL , cell_num * PAR_DFT_COV_ALM_VAL * 0.1);
		param_set_data(PAR_ID_BOV_ALM_RCV , cell_num * PAR_DFT_COV_ALM_RCV * 0.1);
		param_set_data(PAR_ID_BOV_PRP_VAL , cell_num * PAR_DFT_COV_PRP_VAL * 0.1);
		param_set_data(PAR_ID_BOV_PRP_RCV , cell_num * PAR_DFT_COV_PRP_RCV * 0.1);
		
		/* 总压欠压 */
		param_set_data(PAR_ID_BUV_ALM_VAL , cell_num * PAR_DFT_CUV_ALM_VAL * 0.1);
		param_set_data(PAR_ID_BUV_ALM_RCV , cell_num * PAR_DFT_CUV_ALM_RCV * 0.1);
		param_set_data(PAR_ID_BUV_PRP_VAL , cell_num * PAR_DFT_CUV_PRP_VAL * 0.1);
		param_set_data(PAR_ID_BUV_PRP_RCV , cell_num * PAR_DFT_CUV_PRP_RCV * 0.1);
		
		param_set_data(PAR_ID_SOP_DV , PAR_DFT_SOP_DV * cell_num / PAR_DFT_CELL_NUM);
		param_set_data(PAR_ID_SOP_CV , PAR_DFT_SOP_CV * cell_num / PAR_DFT_CELL_NUM);
		
		param_set_data(PAR_ID_FULL_CHG_VOLT ,PAR_DFT_FULL_CHG_VOLT * param_buf[PAR_ID_CB_CELL_NUM] /PAR_DFT_CELL_NUM);
		param_set_data(PAR_ID_CB_TEMP_NUM   , cell_num * 0.25);
		
		param_save_use_param();
		
		NVIC_SystemReset();
	}
}

void param_save_use_param(void)
{
	param_set_data(PAR_ID_RSOC         , var_get_data(VAR_ID_DISP_SOC));
	param_set_data(PAR_ID_REAL_CAP     , var_get_data(VAR_ID_REAL_CAP));
	
	param_set_data(PAR_ID_ACC_CHG_AH_H , var_get_data(VAR_ID_ACC_CHG_AH_H));
	param_set_data(PAR_ID_ACC_CHG_AH_L , var_get_data(VAR_ID_ACC_CHG_AH_L));
	param_set_data(PAR_ID_ACC_DSG_AH_H , var_get_data(VAR_ID_ACC_DSG_AH_H));
	param_set_data(PAR_ID_ACC_DSG_AH_L , var_get_data(VAR_ID_ACC_DSG_AH_L));
}	

uint8_t param_get_2bits_val(uint16_t par_id , uint8_t bits_pos ,uint16_t *val)
{
	if(par_id >= PAR_ID_BUF_SIZE)
        return FALSE;
    
	*val = (param_buf[par_id] >> bits_pos) & 0x03;
	
    return TRUE;
}

uint8_t param_get_4bits_val(uint16_t par_id , uint8_t bits_pos ,uint16_t *val)
{
	if(par_id >= PAR_ID_BUF_SIZE)
        return FALSE;
    
	*val = (param_buf[par_id] >> bits_pos) & 0x0f;
	
    return TRUE;
}

uint8_t param_get_bit_val(uint16_t par_id , uint8_t bits_pos ,uint16_t *val)
{
	if(par_id >= PAR_ID_BUF_SIZE)
        return FALSE;
    
	*val = (param_buf[par_id] >> bits_pos) & 0x01;
	
    return TRUE;
}
/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void param_check_u16_vrc(uint8_t cmd ,uint16_t *par , uint16_t dft , uint16_t min , uint16_t max)
{
    if((PARAM_RESET == cmd) ||(*par < min) || (*par > max))
    {
        *par = dft;
    }
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
